package com.zjsru.plan2023.oneday.oneDay202301;

import java.util.Arrays;

/**
 * @Author: CookLee
 * @Date: 2023/1/7
 *
 * 将 x 减到 0 的最小操作数
 * 给你一个整数数组 nums 和一个整数 x 。每一次操作时，你应当移除数组 nums 最左边或最右边的元素，然后从 x 中减去该元素的值。请注意，需要 修改 数组以供接下来的操作使用。
 *
 * 输入：nums = [1,1,4,2,3], x = 5
 * 输出：2
 * 解释：最佳解决方案是移除后两个元素，将 x 减到 0 。
 *
 * 输入：nums = [5,6,7,8,9], x = 4
 * 输出：-1
 *
 * 输入：nums = [3,2,20,1,1,3], x = 10
 * 输出：5
 * 解释：最佳解决方案是移除后三个元素和前两个元素（总共 5 次操作），将 x 减到 0 。
 */
public class MinOperations {
    
    /**
     * 滑动窗口
     */
    public int minOperations(int[] nums, int x) {
        int n = nums.length;
        int sum = Arrays.stream(nums).sum();
        //总和小于x时代表即是缩短所有数也无法达到目标
        if (sum < x) {
            return -1;
        }
        int right = 0;
        int lsum = 0, rsum = sum;
        int ans = n + 1;
    
        for (int left = -1; left < n; left++) {
            //窗口开始向右收缩，获取左边的窗口外的值的和
            if (left != -1) {
                lsum += nums[left];
            }
            //窗口两边外的值 小于 目标值的时候 说明窗口需要向右移动，rsum表示右边剩余值的和
            while (right < n && lsum + rsum > x) {
                rsum -= nums[right];
                ++right;
            }
            //找到了一组答案:(left + 1) + (n - right)
            if (lsum + rsum == x) {
                ans = Math.min(ans, (left + 1) + (n - right));
            }
        }
    
        return ans > n ? -1 : ans;
    
    }
    
    public static void main(String[] args) {
        MinOperations minOperations = new MinOperations();
        int[] nums = new int[] {1, 1, 4, 2, 3};
        int x = 5;
        System.out.println(minOperations.minOperations(nums, x));
    }
}
